import { IDomEditor, DomEditor, SlateEditor, SlateRange, SlateTransforms } from '@wangeditor/editor';
import { DavinciBlockLink } from '../custom-types.ts';
import { replaceSymbols } from './index.ts';
/**
 * 校验 link
 * @param menuKey menu key
 * @param editor editor
 * @param text menu text
 * @param url menu url
 */
async function check(menuKey: string, editor: IDomEditor, text: string, url: string): Promise<boolean> {
	const { checkLink } = editor.getMenuConfig(menuKey);
	if (checkLink) {
		return checkLink(text, url);
	}
	return true;
}

/**
 * 转换链接 url
 * @param menuKey menu key
 * @param editor editor
 * @param url url
 * @returns parsedUrl
 */
async function parse(menuKey: string, editor: IDomEditor, url: string): Promise<string> {
	const { parseLinkUrl } = editor.getMenuConfig(menuKey);
	if (parseLinkUrl) {
		const newUrl = await parseLinkUrl(url);
		return newUrl;
	}
	return url;
}

export function isMenuDisabled(editor: IDomEditor): boolean {
	if (editor.selection == null) return true;
	const selectedElems = DomEditor.getSelectedElems(editor);
	return selectedElems.some(elem => {
		// @ts-ignore
		const { type } = elem;
		if (editor.isVoid(elem)) return true;
		if (['pre', 'code', 'link'].includes(type)) return true;
	});
}

/**
 * 生成 link node
 * @param url url
 * @param text text
 */
function genLinkNode(url: string, text?: string): DavinciBlockLink {
	const linkNode: DavinciBlockLink = {
		type: 'davinci-link',
		link: replaceSymbols(url),
		content: text ?? url,
		children: [{ text: '' }]
	};
	return linkNode;
}

/**
 * 插入 link
 * @param editor editor
 * @param text text
 * @param url url
 */
export async function insertLink(editor: IDomEditor, text: string, url: string) {
	if (!url) return;
	if (!text) text = url; // 无 text 则用 url 代替

	// 还原选区
	editor.restoreSelection();

	if (isMenuDisabled(editor)) return;

	// 校验
	const checkRes = await check('insertDavinciBlockLink', editor, text, url);
	if (!checkRes) return; // 校验未通过

	// 转换 url
	const parsedUrl = await parse('insertDavinciBlockLink', editor, url);

	// 判断选区是否折叠
	const { selection } = editor;
	if (selection == null) return;
	const isCollapsed = SlateRange.isCollapsed(selection);

	// 执行：插入链接
	if (isCollapsed) {
		// 链接前后插入空格，方便操作
		// editor.insertText(' ')
		const linkNode = genLinkNode(parsedUrl, text);
		SlateTransforms.insertNodes(editor, linkNode);
		editor.insertFragment([{ text: ' ' }]);
		editor.move(1);
	}
}
